package cn.wsalix.shop.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Observable;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.anlaser.admin.BaseUser;
import cn.anlaser.exception.NutException;
import cn.anlaser.form.UploadFileForm;
import cn.anlaser.page.QueryPage;
import cn.anlaser.page.QuerySpecification;
import cn.anlaser.service.impl.SimpleServiceImpl;
import cn.anlaser.status.FlagEnum;
import cn.anlaser.type.FileTypeEnum;
import cn.anlaser.type.ImageTypeEnum;
import cn.anlaser.utils.DynamicSpecifications;
import cn.anlaser.utils.SearchFilter;
import cn.anlaser.utils.SearchFilter.Operator;
import cn.wsalix.biz.entity.Category;
import cn.wsalix.biz.form.CategoryForm;
import cn.wsalix.biz.form.FreemarkerForm;
import cn.wsalix.biz.service.CategoryService;
import cn.wsalix.config.AppConfig;
import cn.wsalix.observable.service.FileUploadService;
import cn.wsalix.observable.service.GenerateService;
import cn.wsalix.shop.entity.Brand;
import cn.wsalix.shop.entity.Origin;
import cn.wsalix.shop.entity.Product;
import cn.wsalix.shop.entity.Shop;
import cn.wsalix.shop.form.ProductForm;
import cn.wsalix.shop.repository.ProductRepository;
import cn.wsalix.shop.repository.RelationProductRepository;
import cn.wsalix.shop.service.BrandService;
import cn.wsalix.shop.service.OriginService;
import cn.wsalix.shop.service.PriceService;
import cn.wsalix.shop.service.ProductService;
import cn.wsalix.shop.service.ShopService;
import cn.wsalix.shop.status.ProductEnum;
import cn.wsalix.shop.status.ShopOperateEnum;
import cn.wsalix.shop.type.ProductTypeEnum;


@Service("productService")
public class ProductServiceImpl extends
		SimpleServiceImpl<ProductForm, ProductRepository, Product> implements
		ProductService {
	@Autowired
	private ProductRepository productRepository;
	@Autowired
	private ShopService shopService;
	@Autowired
	private PriceService productPriceService;
	@Autowired
	private CategoryService categoryService;

	@Autowired
	private BrandService brandService;
	@Autowired
	private RelationProductRepository relationProductRepository;
	@Autowired
	private OriginService originService;
	@Autowired
	private AppConfig appConfig;

	@Override
	public String module() {
		return "/admin/product";
	}

	@Override
	public ProductRepository getRepository() {
		return productRepository;
	}

	@Override
	public QueryPage<Product> findAll(QuerySpecification<Product> spec,
			Pageable pageable) {
		// TODO Auto-generated method stub
		return super.findAll(spec, pageable);
	}

	@Cacheable(value = "productCache")
	@Override
	public List<Product> findByForm(ProductForm form) {
		// TODO Auto-generated method stub
		return super.findByForm(form);
	}

	@Transactional
	@Override
	public Product add(ProductForm form) {
		Product obj = productRepository.findOne(form.getId());
		/*
		 * if (form.getShop() != null) { obj.setShop(form.getShop()); } else if
		 * (form.getShopId() != null && form.getShopId() != 0) { Shop shop =
		 * shopService.findById(form.getShopId()); obj.setShop(shop); }
		 */
		if (form.getParentCatId() != null && form.getParentCatId() != 0) {
			Category category = categoryService.findById(form.getParentCatId());
			obj.setParentCat(category);
		}
		if (form.getCatId() != null && form.getCatId() != 0) {
			Category category = categoryService.findById(form.getCatId());
			obj.setCategory(category);
		}
		if (form.getPostfree() != null && form.getPostfree() != 0) {
			obj.setPostfree(form.getPostfree());
		} else {
			obj.setPostfree(0);
		}
		if (form.getCount() != null && form.getCount() != 0) {
			obj.setCount(form.getCount());
		} else {
			obj.setCount(0);
		}
		// form.setPriceSrc(0);
		// form.setPrice(0);
		// form.setPriceTuan(0);
		traversalAssign(form, obj);

		obj.setFlag(FlagEnum.valid);
		obj = add(obj);
		if (form.getPrice() != null && form.getPrice() != 0) {
			productPriceService.addByProduct(obj);
		}
		return obj;
	}

	@CacheEvict(value = "productCache", key = "#entity.getId()")
	@Transactional
	@Override
	public Product edit(Product entity) {
		// TODO Auto-generated method stub
		return super.edit(entity);
	}

	// @Cacheable(value = "idCache", key = "#id")
	@CacheEvict(value = "productCache", key = "#form.getId()")
	@Transactional
	@Override
	public Product edit(ProductForm form) {
		Product obj = productRepository.findOne(form.getId());
		if (form.getShopOperate() != null) {
			if (form.getShopOperate().ordinal() == ShopOperateEnum.stock
					.ordinal()) {// 进货
				obj.setCount(obj.getCount() + form.getCount());
			}
			if (form.getShopOperate().ordinal() == ShopOperateEnum.onsell
					.ordinal()) {// 上架
				if (obj.getCount() > 0) {// 存在商品才可以上架
					obj.setStatus(ProductEnum.onsell);
				} else {

				}
			}
			if (form.getShopOperate().ordinal() == ShopOperateEnum.undercarriage
					.ordinal()) {// 下架
				obj.setStatus(ProductEnum.undercarriage);
			}
			return super.edit(obj);
		}
		/*
		 * if (form.getSavePath() != null &&
		 * !form.getSavePath().trim().equals("")) {
		 * 
		 * UploadFile uploadFile = new UploadFile();
		 * uploadFile.setFkId(obj.getId());
		 * uploadFile.setType(FileTypeEnum.product);
		 * uploadFile.setStatus(FileEnum.release);
		 * uploadFile.setSavePath(form.getSavePath());
		 * uploadFile.setHttpUrl(form.getHttpUrl());
		 * uploadFileService.add(uploadFile);
		 * 
		 * if (form.getUploadType() != null &&
		 * form.getUploadType().equals("logo")) {
		 * obj.setLogo(form.getHttpUrl()); } else { return obj; } }
		 */
		if (form.getParentCatId() != null && form.getParentCatId() != 0) {
			Category category = categoryService.findById(form.getParentCatId());
			obj.setParentCat(category);
		}
		if (form.getPrice() != null && form.getPrice() > 0) {
			obj.setPrice(form.getPrice());
		}
		if (form.getCatId() != null && form.getCatId() != 0) {
			Category category = categoryService.findById(form.getCatId());
			obj.setCategory(category);
		}
		if (form.getCount() != null && form.getCount() != 0) {
			obj.setCount(form.getCount());
		}

		if (form.getBrandItem() != null) {
			obj.setBrand(form.getBrandItem().getName());
			obj.setBrandLogo(form.getBrandItem().getLogo());
		}
		if (form.getOriginItem() != null) {
			obj.setOrigin(form.getOriginItem().getName());
			obj.setOriginLogo(form.getOriginItem().getLogo());
		}
		if (form.getName() != null && !form.getName().trim().equals("")) {
			obj.setName(form.getName());
		}
		if (form.getRemark() != null && !form.getRemark().trim().equals("")) {
			obj.setRemark(form.getRemark());
		}
		if (form.getStatus() != null) {
			if (form.getStatus().ordinal() == ProductEnum.onsell.ordinal()) {
				if (obj.getPrice() == null || obj.getPrice() <= 0) {
					throw new NutException("商品[" + form.getId()
							+ "]价格等于、小于0，商品不能上架");
				}
			}
			obj.setStatus(ProductEnum.onsell);
		}
		return super.edit(obj);
	}

	@Override
	public Class<Product> getEntityClazz() {
		return Product.class;
	}

	@Override
	public Map<String, SearchFilter> buildByForm(ProductForm form) {
		Map<String, SearchFilter> filters = buildFilter(form);
		if (form.getBrandId() != null && form.getBrandId() != 0) {
			filters.put("brandItem.id", new SearchFilter("brandItem.id",
					Operator.EQ, form.getBrandId()));
		}
		if (form.getBrand() != null && !form.getBrand().equals("")) {
			filters.put("brand",
					new SearchFilter("brand", Operator.EQ, form.getBrand()));
		}
		if (form.getOriginId() != null && form.getOriginId() != 0) {
			filters.put("originItem.id", new SearchFilter("originItem.id",
					Operator.EQ, form.getOriginId()));
		}
		if (form.getOrigin() != null && !form.getOrigin().equals("")) {
			filters.put("origin",
					new SearchFilter("origin", Operator.EQ, form.getOrigin()));
		}
		if (form.getParentCatId() != null && form.getParentCatId() != 0) {
			filters.put("parentCat.id", new SearchFilter("parentCat.id",
					Operator.EQ, form.getParentCatId()));
		}
		/*
		 * if (form.getShopId() != null && form.getShopId() != 0) {
		 * filters.put("shop.id", new SearchFilter("shop.id", Operator.EQ,
		 * form.getShopId())); }
		 */
		if (form.getCatId() != null && form.getCatId() != 0) {
			filters.put("category.id", new SearchFilter("category.id",
					Operator.EQ, form.getCatId()));
		}
		if (form.getShopOperate() != null) {
			if (form.getShopOperate().ordinal() == ShopOperateEnum.lack
					.ordinal()) {// 查询缺货
				filters.put("count", new SearchFilter("count", Operator.EQ, 0));
			}
		}
		if (form.isTuanQuery()) {
			if (form.isTuan()) {
				filters.put("tuan", new SearchFilter("tuan", Operator.EQ, true));
			} else {
				filters.put("tuan",
						new SearchFilter("tuan", Operator.EQ, false));
			}
		}
		if (form.getStatus() != null) {
			filters.put("status",
					new SearchFilter("status", Operator.EQ, form.getStatus()));
		}

		if (form.isCatNull()) {
			filters.put("parent", new SearchFilter("category.id",
					Operator.ISNULL, null));
		}

		return filters;
	}

	@Override
	public List<Product> findsByCatId(Long catId) {
		ProductForm productForm = new ProductForm();
		productForm.setCatId(catId);
		QuerySpecification<Product> spec = DynamicSpecifications
				.bySearchFilter(buildByForm(productForm).values(),
						getEntityClazz());
		return productRepository.findAll(spec);
	}

	@Transactional
	@Override
	public Product getNew(ProductForm form) {
		BaseUser user = userUtils.getUser();
		ProductForm queryForm = new ProductForm();
		queryForm.setFlag(FlagEnum.create);
		queryForm.setCreatedBy(user.getId());
		if (form.getCatId() != null && form.getCatId() != 0) {
			queryForm.setCatId(form.getCatId());
		}
		if (form.getShopId() != null && form.getShopId() != 0) {
			queryForm.setShopId(form.getShopId());
		}
		List<Product> resLst = findByForm(queryForm);
		if (!resLst.isEmpty()) {
			return resLst.get(0);
		} else {
			form.setFlag(FlagEnum.create);
			form.setCreatedBy(user.getCreatedBy());
			form.setStatus(ProductEnum.edit);
			form.setLogo(appConfig.getDefualtImage());
			return super.add(form);
		}
	}

	/*
	 * @Override public void update(Observable o, Object arg) { if (o instanceof
	 * ProductChangeService) { ProductForm form = (ProductForm) arg; edit(form);
	 * } }
	 */
	@Transactional
	@Override
	public void brand(ProductForm form) {
		Brand brand = brandService.findById(form.getBrandId());
		form.setBrandItem(brand);
		edit(form);
	}

	@Transactional
	@Override
	public void origin(ProductForm form) {
		Origin origin = originService.findById(form.getOriginId());
		form.setOriginItem(origin);
		edit(form);
	}

	@Override
	public List<Product> findsByUnCatId(Long catId) {
		ProductForm productForm = new ProductForm();
		productForm.setCatNull(true);
		QuerySpecification<Product> spec = DynamicSpecifications
				.bySearchFilter(buildByForm(productForm).values(),
						getEntityClazz());
		return productRepository.findAll(spec);
	}

	@Transactional
	@Override
	public void update(Observable o, Object arg) {
		if (o instanceof FileUploadService) {
			FileUploadService fileUploadService = (FileUploadService) o;
			if (arg instanceof UploadFileForm) {
				UploadFileForm obj = (UploadFileForm) arg;
				if (obj.getType().ordinal() == FileTypeEnum.image.ordinal()) {
					if (obj.getImageType().equals( ImageTypeEnum.product.name())) {
						if (obj.getCode() != null
								&& obj.getCode().equals("logo")) {
							Product product = productRepository.findOne(obj
									.getFkId());
							product.setLogo(obj.getHttpUrl());
							super.edit(product);
							// fileUploadService.setObj(product);
						}

					}
				}
			}
		}
		if (o instanceof GenerateService) {
			GenerateService service = (GenerateService) o;
			FreemarkerForm form = (FreemarkerForm) arg;
			Product product = productRepository.findOne(form.getId());
		}
	}

	@Override
	public List<Category> findCatLst(CategoryForm queryForm) {
		BaseUser user = userUtils.getUser();
		queryForm.setFlag(FlagEnum.valid);
		queryForm.setCreatedBy(user.getId());
		return categoryService.findByForm(queryForm);
	}

	@Override
	public List<Product> findByShopId(Long shopId) {
		return relationProductRepository.findByTypeAndFkid(shopId,
				ProductTypeEnum.shop);
	}

	@Override
	public List<Product> findByTypeAndFkidAndCat(ProductTypeEnum productType,
			Shop shop, Long catId) {
		return relationProductRepository.findByTypeAndFkidAndCat(shop.getId(), catId,
				productType);
	}

	@Override
	public List<Product> findByUnShopId(Long shopId, Long userId) {
		List<Product> resultLst = relationProductRepository.findByTypeAndFkid(
				shopId, ProductTypeEnum.shop);
		ProductForm form = new ProductForm();
		form.setFlag(FlagEnum.valid);
		form.setCreatedBy(userId);
		List<Product> srcLst = findByForm(form);
		List<Product> resLst = new ArrayList<Product>();
		for (Product obj : srcLst) {
			if (resultLst.contains(obj)) {
				obj.setSelect(true);
			}
			resLst.add(obj);
		}
		return resLst;
	}

	@Transactional
	@Override
	public void undercar(ProductForm form) {
		Product obj = findById(form.getId());
		obj.setStatus(ProductEnum.undercarriage);
		super.edit(obj);
	}

	@Transactional
	@Override
	public void ready(Long productId) {
		Product obj = findById(productId);
		obj.setStatus(ProductEnum.ready);
		super.edit(obj);
	}

	@Transactional
	@Override
	public Product pass(Long productId) {
		Product obj = findById(productId);
		obj.setStatus(ProductEnum.unPass);
		return super.edit(obj);
	}

	@Transactional
	@Override
	public Product unPass(ProductForm form) {
		Product obj = findById(form.getId());
		obj.setStatus(ProductEnum.unPass);
		return super.edit(obj);
	}
}
